<?php

declare (strict_types=1);
namespace App\Model\Service;

use App\Model\CallBase;
use App\Model\Guild\GuildHost;
use App\Model\Guild\GuildManage;
use App\Model\HostBlacklist;
use App\Model\HostPoolForNew;
use App\Model\Setting\SettingUserLevel;
use App\Model\User;
use App\Model\UserChat;
use App\Model\UserProfile;
use App\Model\VideoCall;
use App\Model\VoiceCall;
use Hyperf\Cache\Annotation\Cacheable;
use Hyperf\DbConnection\Db;
use Psr\EventDispatcher\EventDispatcherInterface;
use Hyperf\Di\Annotation\Inject;
class CacheService
{
    use \Hyperf\Di\Aop\ProxyTrait;
    use \Hyperf\Di\Aop\PropertyHandlerTrait;
    function __construct()
    {
        $this->__handlePropertyHandler(__CLASS__);
    }
    /**
     * @Inject
     * @var EventDispatcherInterface
     */
    protected $dispatcher;
    public function flushCache($userId)
    {
        // $this->dispatcher->dispatch(new DeleteListenerEvent('user-update', [$userId]));
        return true;
    }
    /**
     * 无效的用户ID（拉黑，注销等，可扩展）
     * @Cacheable(prefix="invalid_user", ttl=3600, listener="invalid_user_update")
     */
    static function invalidUsers() : array
    {
        $__function__ = __FUNCTION__;
        $__method__ = __METHOD__;
        return self::__proxyCall(__CLASS__, __FUNCTION__, self::__getParamsMap(__CLASS__, __FUNCTION__, func_get_args()), function () use($__function__, $__method__) {
            log_info($__method__);
            $status = [User::STATUS_CANCELLATTED, User::STATUS_FREEZE];
            $userIds = User::whereIn('status', $status)->pluck('id')->toArray();
            return $userIds;
        });
    }
    /**
     * 黑名单主播ID
     * @Cacheable(prefix="black_hosts", ttl=300, listener="black_hosts_update")
     */
    static function blackHosts() : array
    {
        $__function__ = __FUNCTION__;
        $__method__ = __METHOD__;
        return self::__proxyCall(__CLASS__, __FUNCTION__, self::__getParamsMap(__CLASS__, __FUNCTION__, func_get_args()), function () use($__function__, $__method__) {
            log_info($__method__);
            return HostBlacklist::getHostIds();
        });
    }
    /**
     * 分渠道的主播ID
     * @Cacheable(prefix="channel_hosts", ttl=300, value="_#{channel}", listener="channel_hosts_update")
     */
    static function channelHosts($channel = '') : array
    {
        $__function__ = __FUNCTION__;
        $__method__ = __METHOD__;
        return self::__proxyCall(__CLASS__, __FUNCTION__, self::__getParamsMap(__CLASS__, __FUNCTION__, func_get_args()), function ($channel = '') use($__function__, $__method__) {
            if (!$channel) {
                return [];
            }
            log_info($__method__ . "=={$channel}");
            return Db::table('user_profile')->join('user', function ($join) use($channel) {
                $where = [
                    ['status', '=', User::STATUS_OK],
                    // ['is_official', 0],
                    ['role', UserProfile::ROLE_HOST],
                ];
                if (is_array($channel)) {
                    $join->on('user.id', '=', 'user_profile.user_id')->whereIn('channel', $channel);
                } else {
                    $where[] = ['channel', $channel];
                    $join->on('user.id', '=', 'user_profile.user_id')->where($where);
                }
            })->pluck('channel', 'user_id')->toArray();
        });
    }
    /**
     * 获取主播的公会分成
     * @Cacheable(prefix="guild_host_share", ttl=300, value="_#{hostId}", listener="guild_host_share_update")
     */
    static function getGuildHostSharePercent($hostId = 0)
    {
        $__function__ = __FUNCTION__;
        $__method__ = __METHOD__;
        return self::__proxyCall(__CLASS__, __FUNCTION__, self::__getParamsMap(__CLASS__, __FUNCTION__, func_get_args()), function ($hostId = 0) use($__function__, $__method__) {
            if (!$hostId) {
                return 0;
            }
            $where = ['host_user_id' => $hostId, 'status' => GuildHost::STATUS_BIND];
            $data = GuildHost::where($where)->first();
            if (!$data) {
                $percent = 0;
            } else {
                $guild = GuildManage::find($data->guild_manage_id);
                $percent = $guild ? $guild->host_share_ratio : 0;
            }
            log_info($__method__ . "=={$hostId}=={$percent}");
            return $percent;
        });
    }
    /**
     * 获取用户等级配置
     * @Cacheable(prefix="setting_user_level", ttl=120, value="_#{levelType}", listener="setting_user_level_update")
     */
    static function getUserLevelSetting($levelType = 1)
    {
        $__function__ = __FUNCTION__;
        $__method__ = __METHOD__;
        return self::__proxyCall(__CLASS__, __FUNCTION__, self::__getParamsMap(__CLASS__, __FUNCTION__, func_get_args()), function ($levelType = 1) use($__function__, $__method__) {
            log_info($__method__ . "=={$levelType}");
            $data = SettingUserLevel::where(['level_type' => $levelType, 'flag' => 1])->orderBy('level', 'asc')->get()->toArray();
            $ret = [];
            foreach ($data as $item) {
                $ret[] = ['level' => $item['level'], 'level_value' => $item['number'], 'chat_coin_setting' => $item['chat_coin_setting'], 'voice_coin_setting' => $item['voice_coin_setting'], 'video_coin_setting' => $item['video_coin_setting']];
            }
            return $ret;
        });
    }
    /**
     * 获取用户等级配置
     * @Cacheable(prefix="setting_user_coin", ttl=120, value="_#{coinField}", listener="setting_user_coin_update")
     */
    static function getCoinSetting($coinField = 'voice_coin_setting')
    {
        $__function__ = __FUNCTION__;
        $__method__ = __METHOD__;
        return self::__proxyCall(__CLASS__, __FUNCTION__, self::__getParamsMap(__CLASS__, __FUNCTION__, func_get_args()), function ($coinField = 'voice_coin_setting') use($__function__, $__method__) {
            log_info($__method__ . "=={$coinField}");
            $data = SettingUserLevel::where(['level_type' => SettingUserLevel::TYPE_CHARM, 'flag' => 1])->orderBy('number', 'desc')->get()->toArray();
            $coinSetArr = [];
            foreach ($data as $item) {
                $coinSetArr[$item[$coinField]] = ['charm_limit' => $item['number'], 'coin' => $item[$coinField], 'level_limit' => $item['level']];
            }
            array_multisort(array_column($coinSetArr, 'charm_limit'), SORT_ASC, $coinSetArr);
            //私信收费
            if ($coinField == 'chat_coin_setting') {
                // array_unshift($coinSetArr, [
                //     'charm_limit' => 0,
                //     'coin' => 0.0,
                //     'level_limit' => 0
                // ]);
                return array_values($coinSetArr);
            }
            $data = [];
            $coinArr = array_values($coinSetArr);
            for ($coin = $coinArr[0]['coin']; $coin <= max(array_column($coinArr, 'coin'));) {
                $setting = SettingUserLevel::pickCharmLimitByCoin($coin, $coinArr);
                $data[] = ['coin' => $coin, 'charm_limit' => $setting['charm'], 'level_limit' => $setting['level']];
                $coin += 1;
            }
            return $data;
        });
    }
    /**
     * 根据分类条件筛选出主播ID
     * @Cacheable(prefix="host_by_cate", ttl=120, value="_#{hostCate}", listener="host_by_cate_update")
     */
    static function getHostsByCate($hostCate = UserProfile::HOST_CATE_A)
    {
        $__function__ = __FUNCTION__;
        $__method__ = __METHOD__;
        return self::__proxyCall(__CLASS__, __FUNCTION__, self::__getParamsMap(__CLASS__, __FUNCTION__, func_get_args()), function ($hostCate = UserProfile::HOST_CATE_A) use($__function__, $__method__) {
            //自己运营的主播池
            if ($hostCate == UserProfile::HOST_CATE_OFFICIAL) {
                return HostPoolForNew::getValidHosts();
            }
            return Db::table('user_profile')->join('user', function ($join) use($hostCate) {
                $where = [['status', '=', User::STATUS_OK], ['role', UserProfile::ROLE_HOST], ['is_official', 0], ['host_cate', $hostCate]];
                $join->on('user.id', '=', 'user_profile.user_id')->where($where);
            })->orderBy('user_profile.id', 'desc')->pluck('user_id')->toArray();
        });
    }
    /**
     * 获取禁言状态的用户
     * @Cacheable(prefix="forbidden_user", ttl=120, listener="forbidden_user_update")
     */
    static function getForbiddenUsers()
    {
        $__function__ = __FUNCTION__;
        $__method__ = __METHOD__;
        return self::__proxyCall(__CLASS__, __FUNCTION__, self::__getParamsMap(__CLASS__, __FUNCTION__, func_get_args()), function () use($__function__, $__method__) {
            return User::where('status', User::STATUS_FORBID)->pluck('id')->toArray();
        });
    }
    /**
     * 获取通话过的用户
     * @Cacheable(prefix="called_users", ttl=120, value="_#{userId}_#{callType}", listener="called_users_update")
     */
    static function getCalledUsers($userId = 0, $callType = VideoCall::CALL_TYPE)
    {
        $__function__ = __FUNCTION__;
        $__method__ = __METHOD__;
        return self::__proxyCall(__CLASS__, __FUNCTION__, self::__getParamsMap(__CLASS__, __FUNCTION__, func_get_args()), function ($userId = 0, $callType = VideoCall::CALL_TYPE) use($__function__, $__method__) {
            log_info($__method__ . "=={$userId}");
            $callClass = $callType == VideoCall::CALL_TYPE ? VideoCall::class : VoiceCall::class;
            $where = [['user_id', $userId]];
            $orWhere = [['chat_user_id', $userId]];
            $calledUserIds = $callClass::where($where)->whereIn('status', CallBase::DONE_STATUS)->pluck('chat_user_id')->toArray();
            $calledUserIds = array_merge($calledUserIds, $callClass::where($orWhere)->whereIn('status', CallBase::DONE_STATUS)->pluck('user_id')->toArray());
            return array_unique($calledUserIds);
        });
    }
    /**
     * 获取聊天过的用户
     * @Cacheable(prefix="chated_users", ttl=120, value="_#{userId}", listener="chated_users")
     */
    static function getChatedUsers($userId = 0)
    {
        $__function__ = __FUNCTION__;
        $__method__ = __METHOD__;
        return self::__proxyCall(__CLASS__, __FUNCTION__, self::__getParamsMap(__CLASS__, __FUNCTION__, func_get_args()), function ($userId = 0) use($__function__, $__method__) {
            log_info($__method__ . "=={$userId}");
            $where = [['user_id', $userId]];
            $orWhere = [['chat_user_id', $userId]];
            $where[] = $orWhere[] = ['msg_num', '>', 1];
            $where[] = $orWhere[] = ['chat_msg_num', '>', 1];
            $logs = UserChat::where($where)->orWhere(function ($query) use($orWhere) {
                $query->where($orWhere);
            })->select(['chat_user_id', 'user_id'])->get()->toArray();
            $chatedUserIds = [];
            foreach ($logs as $log) {
                $uid = $log['user_id'] == $userId ? $log['chat_user_id'] : $log['user_id'];
                !in_array($uid, $chatedUserIds) && array_push($chatedUserIds, $uid);
            }
            return $chatedUserIds;
        });
    }
}